/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许，不可做商业用途！
 *
 * 版权所有，侵权必究！
 */
package com.yami.shop.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yami.shop.bean.enums.RetainedDateType;
import com.yami.shop.bean.enums.RetainedType;
import com.yami.shop.bean.model.FlowLog;
import com.yami.shop.bean.model.FlowUserAnalysis;
import com.yami.shop.bean.param.CustomerRetainedReqParam;
import com.yami.shop.dao.FlowLogMapper;
import com.yami.shop.service.*;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 用户流量分析
 *
 * @author YXF
 * @date 2020-07-13 13:18:33
 */
@Service
@AllArgsConstructor
@Slf4j
public class FlowServiceImpl extends ServiceImpl<FlowLogMapper, FlowLog> implements FlowService {

    private final FlowLogService flowLogService;
    private final FlowPageAnalysisService flowPageAnalysisService;
    private final FlowRouteAnalysisService flowRouteAnalysisService;
    private final FlowUserAnalysisService flowUserAnalysisService;
    private final OrderDataAnalysisService orderDataAnalysisService;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void statisticalData() {
        //已存储数据的最新的日期（统计的开始时间）
        Date startTime = flowLogService.getMinCreateTime();
        if (Objects.isNull(startTime)){
            Date minCreateTime = flowLogService.getMinCreateTime();
            if (Objects.isNull(minCreateTime)){
                return;
            }
            DateTime dateTime = DateUtil.beginOfDay(minCreateTime);
            startTime = DateUtil.offsetDay(dateTime, -1);
        }
        //没有数据直接退出方法
        if (Objects.isNull(startTime)){
            return;
        }
        //统计的结束时间
        Date endTime = DateUtil.offsetDay(startTime, 1);
        //当天开始时间
        Long currentTime = DateUtil.beginOfDay(new Date()).getTime();
        //按天统计数据
        while (endTime.getTime() <= currentTime){
            try {
                statistical(startTime,endTime);
            } catch (Exception e) {
                String format = DateUtil.format(startTime, "yyyy-MM-dd HH:mm:ss");
                log.error("时间为{}的数据统计异常, 错误信息为：{}", format, e.getMessage());
            }
            startTime = DateUtil.offsetDay(startTime, 1);
            endTime = DateUtil.offsetDay(endTime, 1);
        }
        // 访问数据更新后,刷新留存数据缓存
        refreshRetainedData();
    }

    private void statistical(Date startTime, Date endTime){
        List<FlowLog> flowLogList = flowLogService.getFlowLogByDate(startTime,endTime);
        if (CollUtil.isEmpty(flowLogList)) {
            return;
        }
        Map<String, List<FlowLog>> flowAnalysisLogMap = flowLogList.stream().collect(Collectors.groupingBy(FlowLog::getUuidSession));
        // 统计的部分用户数据
        Map<String, FlowUserAnalysis> flowUserAnalysisMap = new HashMap<>(16);
        //统计页面及商品详情页商品数据
        flowPageAnalysisService.getPageDataByLog(flowAnalysisLogMap, startTime, flowUserAnalysisMap);
        //统计用户访问路径数据
        flowRouteAnalysisService.routeInfo(flowLogList,startTime);
        //统计用户数据
        flowUserAnalysisService.statisticalUserData(flowAnalysisLogMap,startTime,flowUserAnalysisMap);
        //清除已经统计过的数据，减轻表的压力（测试时可注掉，重复使用数据）
        flowLogService.deleteAllByDate(startTime,endTime);
    }

    /**
     * 刷新客户留存缓存数据
     */
    @Override
    public void refreshRetainedData() {
        DateTime now = DateUtil.date();
        Date endOfDay =  DateUtil.endOfDay(now);
        List<CustomerRetainedReqParam> list = new ArrayList<>();
        RetainedType[] values = RetainedType.values();
        for (RetainedType type : values) {
            Integer typeValue = type.value();
            RetainedDateType[] retainedDateTypes = RetainedDateType.values();
            for (RetainedDateType retainedDateType : retainedDateTypes) {
                if (Objects.equals(1,retainedDateType.value())) {
                    continue;
                }
                CustomerRetainedReqParam param = new CustomerRetainedReqParam();
                param.setDateRetainType(1);
                param.setDateType(retainedDateType.value());
                param.setRetainType(typeValue);
                int setMonth = 0;
                if (Objects.equals(param.getDateType(),RetainedDateType.THREE_MONTH.value())) {
                    setMonth = 3;
                } else if (Objects.equals(param.getDateType(),RetainedDateType.SIX_MONTH.value())) {
                    setMonth = 6;
                } else if (Objects.equals(param.getDateType(),RetainedDateType.ONE_YEAR.value())) {
                    setMonth = 12;
                }
                Date start =  DateUtil.beginOfDay(DateUtil.offsetMonth(now,-setMonth));
                param.setStartTime(start);
                param.setEndTime(endOfDay);
                list.add(param);
            }
        }
        // 清除缓存
        for (CustomerRetainedReqParam param : list) {
            flowUserAnalysisService.removeCacheVisitRetained(param);
            orderDataAnalysisService.removeCacheTradeRetained(param);
        }
        // 重新拉取数据
        for (CustomerRetainedReqParam param : list) {
            flowUserAnalysisService.getVisitRetained(param);
            orderDataAnalysisService.getTradeRetained(param);
        }

    }
}
